using System;

using Slaks.Descriptions;

namespace Slaks.Readers
{
	[ModuleDescriptionAttribute("TermFileReader supports basic reading terms from file","Slava Kisilevich")]
  public class TermFileReader : FileReader
	{
    public TermFileReader(string filename, System.Text.Encoding encoding) : base(filename,encoding) {}
    public TermFileReader(Slaks.Filters.AFilter filter,string filename, System.Text.Encoding encoding) : 
                                                                        base(filter,filename,encoding) {}
    public override string NextTerm(ref ReaderState state)
    {
      if (m_filter == null) throw new Exception("TermFilter must be registered first");
      string buffer = String.Empty;
      char []ch_before = new char[1];
      char ch_after;
      bool startTerm = false;
      bool endTerm = false;

      if (m_innerBuffer != char.MinValue) 
      {
        if ((m_isOutputPunctuationMarks && 
            (m_innerBufferState == ReaderState.MiddleSentencePunctuation || 
             m_innerBufferState == ReaderState.EndOfSentencePunctuation)) || 
             (m_isOutputSpecialCharacter && m_innerBufferState == ReaderState.SpecialCharacter))
        {
          ch_before[0] = m_innerBuffer;
          m_innerBuffer = char.MinValue;
          state = m_innerBufferState;
          return ch_before[0].ToString();
        }
        else m_innerBuffer = char.MinValue;
      }

      while (!endTerm)
      {
        if (Eof()) break;

        m_stream.Read(ch_before,0,1);

        //middle sentence punctuation mark
        if (m_filter.IsMiddleSentencePunctuationMark(ch_before[0])) 
        {
          if (buffer == String.Empty) 
          {
            if (m_isOutputPunctuationMarks) 
            {
              state = ReaderState.MiddleSentencePunctuation;
              return ch_before[0].ToString();
            }
          }
          else 
          {
            m_innerBuffer = ch_before[0];
            state = ReaderState.Term;
            m_innerBufferState = ReaderState.MiddleSentencePunctuation;
            return buffer;
          }
        }

        //end of sentence punctuation mark
        if (m_filter.IsEndOfSentencePunctuationMark(ch_before[0])) 
        {
          if (buffer == String.Empty) 
          {
            if (m_isOutputPunctuationMarks) 
            {
              state = ReaderState.EndOfSentencePunctuation;
              return ch_before[0].ToString();
            }
          }
          else 
          {
            m_innerBuffer = ch_before[0];
            state = ReaderState.Term;
            m_innerBufferState = ReaderState.EndOfSentencePunctuation;
            return buffer;
          }
        }

        //special character
        if (m_filter.IsSpecialCharacter(ch_before[0]))
        {
          if (buffer == String.Empty) 
          {
            if (m_isOutputSpecialCharacter) 
            {
              state = ReaderState.SpecialCharacter;
              return ch_before[0].ToString();
            }
          }
          else 
          {
            m_innerBuffer = ch_before[0];
            state = ReaderState.Term;
            m_innerBufferState = ReaderState.SpecialCharacter;
            return buffer;
          }
        }

        ch_after = m_filter.Normalize(ch_before[0]);

        if (!m_filter.DoSkipCharInTerm(ch_after) && !m_filter.IsWhiteSpace(ch_after))
        {
          if (ch_after != ' ') 
          {
            buffer += ch_after;
            if (!startTerm) startTerm = true;
          }
        }

        if (m_filter.IsWhiteSpace(ch_after)) 
        {
          if (startTerm) endTerm = true;
        }

      }
      if (buffer == String.Empty) 
      {
          if (m_innerBuffer != char.MinValue) 
          {
            state = m_innerBufferState;
            return m_innerBuffer.ToString();
          }
          state = ReaderState.None;
      }
      else state = ReaderState.Term;
      return buffer;
    }

    public override string ToString()
    {
      return "term file reader";
    }
	}
}
